package at.ac.tuwien.ifs.calendit.basis.gui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.Date;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;

import javax.swing.AbstractButton;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.table.AbstractTableModel;

import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

import at.ac.tuwien.ifs.calendit.basis.helper.Constants;
import at.ac.tuwien.ifs.calendit.dao.ITermin;
import at.ac.tuwien.ifs.calendit.domain.Termin;
/**
 * table model for monatsansicht, which extends abstracttablemodel
 * @author mona
 *
 */
public class JMonatsansichtTableModel extends AbstractTableModel{

	
	private static final long serialVersionUID = 1L;
	public static JTextField jt= new JTextField();
	private ITermin terminDao;
	private XmlBeanFactory xbf;
	private int realYear, realMonth;
	private static String[] col = {"Montag", "Dienstag","Mittwoch", "Donnerstag", 
		"Freitag", "Samstag", "Sonntag"};
	public static JComponent[][] cells ={
		{new JLabel(),new JLabel(),new JLabel(),new JLabel(),new JLabel(),new JLabel(),new JLabel()},
		{new JLabel(),new JLabel(),new JLabel(),new JLabel(),new JLabel(),new JLabel(),new JLabel()},
		{new JLabel(),new JLabel(),new JLabel(),new JLabel(),new JLabel(),new JLabel(),new JLabel()},
		{new JLabel(),new JLabel(),new JLabel(),new JLabel(),new JLabel(),new JLabel(),new JLabel()},
		{new JLabel(),new JLabel(),new JLabel(),new JLabel(),new JLabel(),new JLabel(),new JLabel()},
		{new JLabel(),new JLabel(),new JLabel(),new JLabel(),new JLabel(),new JLabel(),new JLabel()}	
	};
	public static Object[][] rows= {
			{cells[0][0],cells[0][1],cells[0][2],cells[0][3],cells[0][4],cells[0][5],cells[0][6]},
			{cells[1][0],cells[1][1],cells[1][2],cells[1][3],cells[1][4],cells[1][5],cells[1][6]},
			{cells[2][0],cells[2][1],cells[2][2],cells[2][3],cells[2][4],cells[2][5],cells[2][6]},
			{cells[3][0],cells[3][1],cells[3][2],cells[3][3],cells[3][4],cells[3][5],cells[3][6]},
			{cells[4][0],cells[4][1],cells[4][2],cells[4][3],cells[4][4],cells[4][5],cells[4][6]},
            {cells[5][0],cells[5][1],cells[5][2],cells[5][3],cells[5][4],cells[5][5],cells[5][6]}};
	public static Date[] weekdates= new Date[7];
	
	/**
	 * creates a new table model for monatsansicht
	 */
	public JMonatsansichtTableModel() {
		initGUI();
	}
	
	/**
	 * initializes GUI
	 */
	private void initGUI() {
		jt.addActionListener(new TextFieldListener());
		jt.getDocument().addDocumentListener(new DListener());
		
		initDAO();
		initWeekdays();
	}
	
	/**
	 * initializes DAO - needed for getting termine of currentDay
	 */
	private void initDAO(){
		ClassPathResource res = new ClassPathResource(Constants.SPRINGBEANS);
		xbf = new XmlBeanFactory(res);
		terminDao = (ITermin) xbf.getBean("TerminDAO");
	}
	
	/**
	 * initializes weekdays
	 */
	private void initWeekdays() {
		GregorianCalendar cal = new GregorianCalendar(); //Create calendar
        realMonth = cal.get(GregorianCalendar.MONTH); //Get month
        realYear = cal.get(GregorianCalendar.YEAR); //Get year
        refreshCalendar (realMonth, realYear);
	}

	/**
	 * refreshes the monatsansicht-table and fills with termine
	 * if there are any. 
	 * 
	 * @param month: current month 
	 * @param year: current year
	 */
	public void refreshCalendar(int month, int year){
        int nod, dow; //Number Of Days, Start Of Month
              
        //Clear table
        for (int i=0; i<6; i++){
            for (int j=0; j<7; j++){
            	cells[i][j] = new JLabel("");
                rows[i][j] = cells[i][j];
            }
        }
        
        //Get first day of month and number of days
        GregorianCalendar cal = new GregorianCalendar(year, month, 1);
        nod = cal.getActualMaximum(Calendar.DAY_OF_MONTH); 
        if (cal.get(Calendar.DAY_OF_WEEK)==1) dow = 7;
        else dow = cal.get(Calendar.DAY_OF_WEEK)-1;
        
        int row, column;
        List<Termin> daytermine; //list of termine of current day
        
        //iterating through number of days of current month
        for (int day=1; day<=nod; day++){ 
                row = new Integer((day+dow-2)/7);
                column  =  (day+dow-2)%7;
                cells[row][column] = new JLabel("   "+day);
                rows[row][column] = cells[row][column];
                daytermine = getTerminOfDay(day,month,year);
                if(daytermine.size()>0) 
                	initTerminButton(daytermine,day, row, column);
        }
       
    }
	
	/**
	 * initializes a button for a cell if there is a termin
	 * 
	 * @param daytermine: termine of current day
	 * @param day: current day
	 * @param row: row of the table (where button will be placed)
	 * @param col: column of the table (where button will be placed)
	 */
	private void initTerminButton(List<Termin> daytermine,int day, int row, int col) {
		Termin tmp;
		String text = "<html><b>"+day+"</b><br>";
		String tooltip = "<html>";
			tmp = daytermine.get(0);
			text += tmp.getBezeichnung()+"<br>";
			tooltip += ""+tmp.getBeschreibung()+"<br>";
			if (daytermine.size()>1){
				tmp = daytermine.get(1);
				text += tmp.getBezeichnung()+"<br>";
				tooltip += ""+tmp.getBeschreibung()+"<br>";
			}
		if (daytermine.size()>2) {
			for (int i=2; i<daytermine.size(); i++)
				tooltip += ""+daytermine.get(i).getBeschreibung()+"<br>";
		}
		tooltip += "</html>";
		text += "</html>";
		JButton tmpB = new JButton(text);
		tmpB.setHorizontalTextPosition(AbstractButton.LEFT);
		tmpB.setToolTipText(tooltip);
		cells[row][col] = tmpB;
		rows[row][col] = cells[row][col];
	}

	/**
	 * gets termine of a specified date
	 * 
	 * @param day - day of the date 
	 * @param month - month of the date
	 * @param year - year of the date
	 * @return a list of Termin if there are any for the specified date 
	 * (given by day, month and year), returns null if there are no
	 * termine for the given date
	 */
	private List<Termin> getTerminOfDay(int day, int month, int year){
		Termin t = new Termin();
		t.setMitarbeiterID(Constants.UserId);
		Calendar now=new GregorianCalendar(year,month,day);
		java.sql.Date date= new java.sql.Date(now.getTimeInMillis());
		t.setBeginnDatum(date);
		if (terminDao.getTerminToDay(t)!= null) return terminDao.getTerminToDay(t);
		else return null; 
	}


	/**
	 * gets column name of a specified index
	 * 
	 * @param column: column of the table
	 * @return name of the column index
	 */
	public String getColumnName(int column) { 
	    return col[column];
	}
	
	/**
	 * gets row count
	 * @return row count of the table
	 */
	public int getRowCount() {
	    return rows.length;
	}

	/**
	 * gets column count
	 * @return column length of the table
	 */
	public int getColumnCount() {
	    return col.length;
	}

	/**
	 * gets the value of a specified row and column from the table
	 * 
	 * @param row: table row index
	 * @param column: table column index
	 * @return the Object which is placed at specified row and col
	 */
	public Object getValueAt(int row, int column) { 
	      return rows[row][column];
	}

	/**
	 * @return false, because cells are not editable
	 */
	public boolean isCellEditable(int row, int column) {
	    return false;
	}

	public Class<? extends Object> getColumnClass(int column) {
	    return getValueAt(0, column).getClass();
	}
	
	private class TextFieldListener implements ActionListener{
		public void actionPerformed(ActionEvent e) {
		    refreshCalendar (Monatsansicht.currMonth, Monatsansicht.currYear);
		}
	}
	
	private class DListener implements DocumentListener{


		public void changedUpdate(DocumentEvent arg0) {
			refreshCalendar (Monatsansicht.currMonth, Monatsansicht.currYear);
			
		}

		public void insertUpdate(DocumentEvent arg0) {
			refreshCalendar (Monatsansicht.currMonth, Monatsansicht.currYear);
		}

		public void removeUpdate(DocumentEvent arg0) {

			refreshCalendar (Monatsansicht.currMonth, Monatsansicht.currYear);
			
		}
    	
    }
}
